package main

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
)

func HomeHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Gorilla!\n"))
}

func ArticleHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	w.Write([]byte(fmt.Sprintln("Articles Category:", vars["category"], "ID:", vars["id"], "Filter:", vars["filter"])))
}

func ProductHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	w.Write([]byte(fmt.Sprintln("Products key:", vars["key"])))
}

func ProductDetailHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	w.Write([]byte(fmt.Sprintln("Products key:", vars["key"], "Detail")))
}

func loggingMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		defer func(start time.Time) {
			log.Println("uri:", r.RequestURI, "elapse:", time.Now().Sub(start))
		}(time.Now())

		next.ServeHTTP(w, r)
	})
}

func main() {
	r := mux.NewRouter()

	// router
	r.HandleFunc("/", HomeHandler)
	r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).Queries("filter", "{filter:[a-zA-Z]+}").Name("articles")
	r.HandleFunc("/articles/post/{category}/{id:[0-9]+}", ArticleHandler).Methods("POST").Name("articles.post")

	// sub router
	sr := r.PathPrefix("/products").Subrouter()
	sr.HandleFunc("/{key}", ProductHandler)
	sr.HandleFunc("/{key}/detail", ProductDetailHandler).Name("products.detail")

	// middleware
	r.Use(loggingMiddleware)

	// This will serve files under http://localhost:8000/static/<filename>
	r.PathPrefix("/static").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("."))))

	// URL
	fmt.Println(r.Get("articles").URL(
		"category", "book",
		"id", "10",
		"filter", "gorilla",
	))

	fmt.Println(r.Host("{domain}:{port}").
		Path("/articles/{category}/{id:[0-9]+}").
		Queries("filter", "{filter}").URL(
		"domain", "localhost",
		"port", "18911",
		"category", "book",
		"id", "10",
		"filter", "gorilla",
	))

	// Bind to a port and pass our router in
	log.Fatal(http.ListenAndServe(":18911", r))
}
